﻿using System;
using System.Linq;
using Asp.Versioning.ApiExplorer;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;

namespace net.xBei.WebApi.Helper {
    /// <summary>
    /// 快速配置 Swagger
    /// </summary>
    public static class SwaggerHelper {
        private static string ApiTitle { get; set; } = default!;
        private static string Version { get; set; } = default!;
        /// <summary>
        /// 是否设置Swagger
        /// </summary>
        private static bool IsSetupSwagger { get; set; } = false;

        /// <summary>
        /// 设置Swagger
        /// </summary>
        /// <param name="services"></param>
        /// <param name="ApiTitle"></param>
        /// <param name="Version"></param>
        /// <param name="xmlDocument"></param>
        /// <param name="force">设置为 true 会在生产环境下启用（默认不会）</param>
        public static IServiceCollection SetupSwagger(this IServiceCollection services,
                                        string ApiTitle,
                                        string Version,
                                        string xmlDocument,
                                        bool force = false) {
            SwaggerHelper.ApiTitle = ApiTitle;
            SwaggerHelper.Version = Version;
            //SwaggerHelper.Force = force;
            if (WebApplication.Environment.IsProduction() && !force) {
                return services;
            }
            var provider = GetApiVersionDescriptionProvider(services);
            services.AddSwaggerGen(c => {
                c.CustomSchemaIds(type => type.FullName);
                c.OrderActionsBy(orderBy => orderBy.GroupName);
                c.ResolveConflictingActions(api => api.FirstOrDefault());
                if (provider == null) {
                    c.SwaggerDoc(Version, new OpenApiInfo { Title = string.Format("{0} 接口文档", ApiTitle), Version = Version });
                } else {
                    foreach (var item in provider.ApiVersionDescriptions) {
                        c.SwaggerDoc(item.GroupName, new OpenApiInfo {
                            Title = string.Format("{0} 接口文档", ApiTitle),
                            Version = item.ApiVersion.ToString(),
                        });
                    }
                }
                //c.DocumentFilter<ApplyTagDescriptions>();

                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
                    Description = "请输入JWT Token，“Bearer {TOKEN}”",
                    Name = "Authorization",
                    Type = SecuritySchemeType.Http,
                    In = ParameterLocation.Header,
                    Scheme = "bearer",
                    BearerFormat = "JWT"
                });

                c.AddSecurityRequirement(new OpenApiSecurityRequirement() {
                    { new OpenApiSecurityScheme {
                        Reference = new OpenApiReference {
                            Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"
                        }
                    }, Array.Empty<string>() } });
                //c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
                c.IncludeXmlComments(xmlDocument);
            });
            IsSetupSwagger = true;
            return services;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="app"></param>
        public static IApplicationBuilder UseCustomSwaggerUI(this IApplicationBuilder app) {
            if (!IsSetupSwagger) {
                return app;
            }
            app.UseSwagger();
            var provider = GetApiVersionDescriptionProvider(app);
            return app.UseSwaggerUI(c => {
                // c.InjectJavascript("/swagger/ui/zh_CN.js"); // 加载中文包
                if (provider == null) {
                    c.SwaggerEndpoint($"/swagger/{Version}/swagger.json", $"{ApiTitle} API {Version}");
                } else {
                    foreach (var item in provider.ApiVersionDescriptions) {
                        c.SwaggerEndpoint($"/swagger/{item.GroupName}/swagger.json", $"{ApiTitle} API {item.ApiVersion}");
                    }
                }
            });
        }
        internal static IApiVersionDescriptionProvider GetApiVersionDescriptionProvider(this IApplicationBuilder app) {
            return app.ApplicationServices.GetRequiredService<IApiVersionDescriptionProvider>();
        }
        internal static IApiVersionDescriptionProvider GetApiVersionDescriptionProvider(this IServiceCollection services) {
            return services.BuildServiceProvider().GetRequiredService<IApiVersionDescriptionProvider>();

        }
    }// end class

}
